/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "test_hi182x_common.h"

using namespace dev;

namespace drivers {
namespace pcie_nic_card {
namespace hisi {
namespace test {

// ========================= OpticalTransceiver设备测试 =========================

TEST_F(Hi182xAbiTest, create_hi182x_optical_module_success) {
    // 目标：验证OpticalTransceiver设备创建成功
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    // 使用构造函数创建光模块设备实例
    auto device = device_driver->ctor(&m_test_service, "hi182x_optical_module");
    ASSERT_TRUE(device != nullptr);
}

TEST_F(Hi182xAbiTest, create_hi182x_optical_module_null_service) {
    // 目标：验证创建光模块设备时传入空服务指针的错误处理
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    // 测试：传入空服务指针应该返回nullptr
    auto device = device_driver->ctor(nullptr, "hi182x_optical_module");
    EXPECT_EQ(device, nullptr);
}

TEST_F(Hi182xAbiTest, init_hi182x_optical_module_null_params) {
    // 目标：验证使用空参数初始化光模块设备时的错误处理
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = device_driver->ctor(&m_test_service, "hi182x_optical_module_null_test");
    ASSERT_TRUE(device != nullptr);

    // 测试：使用空参数初始化应返回错误
    status_t ret = device_driver->init(device, nullptr, nullptr);
    EXPECT_EQ(ret, STATUS_ERROR);
}

TEST_F(Hi182xAbiTest, init_hi182x_optical_module_with_params) {
    // 目标：验证光模块设备的初始化功能
    // 测试：设置光模块的各种属性（厂商、型号、序列号等）
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_optical_module*>(
        device_driver->ctor(&m_test_service, "hi182x_optical_module_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 配置光模块基本信息
    mc::mutable_dict config;
    config["bmc.dev.OpticalModule"] = mc::dict{
        {"Manufacturer", "Huawei"},           // 厂商
        {"PartNumber", "1234567890"},         // 部件号
        {"SerialNumber", "1234567890"},       // 序列号
        {"MediumType", "1000BASE-T"},         // 介质类型
        {"ConnectorType", "RJ45"},            // 连接器类型
        {"TransmissionDistance", 100},        // 传输距离
    };
    // 配置光模块电流信息
    config["bmc.dev.OpticalModule.Current"] = mc::dict{
        {"TXBiasCurrentMilliAmps", std::vector<double>{100}},  // 发送偏置电流
    };
    // 配置光模块功率信息
    config["bmc.dev.OpticalModule.Power"] = mc::dict{
        {"TXOutputPowerMilliWatts", std::vector<double>{100}},  // 发送功率
        {"RXInputPowerMilliWatts", std::vector<double>{100}},   // 接收功率
    };
    // 配置光模块电压信息
    config["bmc.dev.OpticalModule.Voltage"] = mc::dict{
        {"SupplyVoltage", 100},  // 供电电压
    };
    
    // 执行初始化
    EXPECT_TRUE(device->init(config, mc::dict()));
    
    // 验证基本属性设置成功
    EXPECT_EQ(device->m_optical_module.Manufacturer.get_value(), "Huawei");
    EXPECT_EQ(device->m_optical_module.PartNumber.get_value(), "1234567890");
    EXPECT_EQ(device->m_optical_module.SerialNumber.get_value(), "1234567890");
    EXPECT_EQ(device->m_optical_module.MediumType.get_value(), "1000BASE-T");
    EXPECT_EQ(device->m_optical_module.ConnectorType.get_value(), "RJ45");
    EXPECT_EQ(device->m_optical_module.TransmissionDistance.get_value(), 100);
    
    // 验证电流属性设置成功
    auto value = device->m_optical_module_current.TXBiasCurrentMilliAmps.get_value();
    EXPECT_EQ(value.as<std::vector<double>>(), std::vector<double>{100});
    
    // 验证功率属性设置成功
    value = device->m_optical_module_power.TXOutputPowerMilliWatts.get_value();
    EXPECT_EQ(value.as<std::vector<double>>(), std::vector<double>{100});
    value = device->m_optical_module_power.RXInputPowerMilliWatts.get_value();
    EXPECT_EQ(value.as<std::vector<double>>(), std::vector<double>{100});
    
    // 验证电压属性设置成功
    EXPECT_EQ(device->m_optical_module_voltage.SupplyVoltage.get_value(), 100);
}

TEST_F(Hi182xAbiTest, init_hi182x_optical_module_reset_default_properties) {
    // 目标：验证光模块设备属性重置功能
    // 测试：将所有属性重置为默认值（空字符串、0xFFFF等）
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_optical_module*>(
        device_driver->ctor(&m_test_service, "hi182x_optical_module_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 执行属性重置
    EXPECT_TRUE(device->reset_default_properties());
    
    // 验证字符串属性重置为空
    EXPECT_EQ(device->m_optical_module.Manufacturer.get_value(), "");
    EXPECT_EQ(device->m_optical_module.PartNumber.get_value(), "");
    EXPECT_EQ(device->m_optical_module.SerialNumber.get_value(), "");
    EXPECT_EQ(device->m_optical_module.MediumType.get_value(), "");
    EXPECT_EQ(device->m_optical_module.ConnectorType.get_value(), "");
    EXPECT_EQ(device->m_optical_module.WaveLengthNanometer.get_value(), "");
    EXPECT_EQ(device->m_optical_module.Identifier.get_value(), "");
    
    // 验证数值属性重置为无效值0xFFFF
    EXPECT_EQ(device->m_optical_module.TransmissionDistance.get_value(), 0xFFFF);
    EXPECT_EQ(device->m_optical_module_voltage.SupplyVoltage.get_value(), 0xFFFF);
    EXPECT_EQ(device->m_optical_module_power.TXPowerUpperThresholdCritical.get_value(), 0xFFFF);
    EXPECT_EQ(device->m_optical_module_power.TXPowerLowerThresholdCritical.get_value(), 0xFFFF);
    EXPECT_EQ(device->m_optical_module_voltage.VoltageUpperThresholdCritical.get_value(), 0xFFFF);
    
    // 验证状态属性重置为false
    EXPECT_EQ(device->m_optical_module_status.RXLossState.get_value(), false);
    EXPECT_EQ(device->m_optical_module_status.TXLossState.get_value(), false);
    EXPECT_EQ(device->m_optical_module_status.TXFaultState.get_value(), false);
    
    // 验证向量属性重置为空向量
    auto value = device->m_optical_module_current.TXBiasCurrentMilliAmps.get_value();
    EXPECT_EQ(value.as<std::vector<double>>(), std::vector<double>{});
    value = device->m_optical_module_power.TXOutputPowerMilliWatts.get_value();
    EXPECT_EQ(value.as<std::vector<double>>(), std::vector<double>{});
    value = device->m_optical_module_power.RXInputPowerMilliWatts.get_value();
    EXPECT_EQ(value.as<std::vector<double>>(), std::vector<double>{});
}

TEST_F(Hi182xAbiTest, test_hi182x_optical_module_start_ncsi_protocol) {
    // 目标：验证光模块设备的NCSI协议启动功能
    // 场景：通过MCTP传输启动NCSI通信，用于读取光模块信息
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_optical_module*>(
        device_driver->ctor(&m_test_service, "hi182x_optical_module_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 初始化MCTP物理地址
    uint16_t phy_addr = mctp::init_phy_addr(0, 0, 0);
    
    // 创建MCTP传输对象（用于NCSI消息传输）
    mctp* mctp_object = new mctp(device, phy_addr, MCTP_MESSAGE_TYPE::MCTP_MESSAGE_TYPE_NCSI, "");
    
    // 创建华为NCSI-over-MCTP协议对象
    auto m_ncsi_over_mctp_huawei = std::make_shared<ncsi_over_mctp_huawei>(*mctp_object);
    
    // 启动NCSI协议，周期1000ms
    EXPECT_TRUE(device->start_ncsi_protocol(m_ncsi_over_mctp_huawei, mc::milliseconds(1000)));
    
    // 停止设备
    EXPECT_TRUE(device->stop());
}

// ========================= 光模块工具测试 =========================

// 工具函数：将微伏特转换为毫伏特
static float covert_micro_to_milli(uint16_t value) {
    if (value == 0xFFFF) {  // 无效值
        return 0.0;
    }
    return value / 1000.0;  // 微伏->毫伏
}

TEST_F(Hi182xAbiTest, test_hi182x_card_get_optical_module_info) {
    // 目标：验证光模块信息解析功能
    // 测试：解析NCSI响应中的厂商、型号、序列号、工作电压等信息
    std::vector<uint8_t> rsp_data = {
        0, 0, 0, 0, 0, 0, 7, 219, 0, 0, 13, 0, 76, 57, 57, 81, 70, 48, 50, 48, 
        45, 83, 68, 45, 82, 32, 32, 32, 76, 85, 88, 83, 72, 65, 82, 69, 45, 73, 
        67, 84, 32, 32, 32, 32, 90, 48, 48, 65, 50, 82, 49, 55, 48, 57, 48, 48, 
        48, 48, 54, 49, 17, 3, 35, 0, 255, 255, 0, 90, 0, 0, 12, 178, 0, 0, 255, 255, 
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 
        255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0
    };
    std::string rsp_str(rsp_data.begin(), rsp_data.end());
    auto rsp = reinterpret_cast<oem_huawei_optical_module_info_rsp_t*>(rsp_str.data());
    
    // 准备光模块信息结构体
    ncsi_optical_module_info_t optical_module_info = {};
    auto optical_module_info_ptr = &optical_module_info;

    // 从NCSI响应中提取光模块信息
    memcpy(optical_module_info_ptr->manufacturer, rsp->vendor, 16);      // 厂商名称
    memcpy(optical_module_info_ptr->part_number, rsp->part_number, 16);  // 部件号
    memcpy(optical_module_info_ptr->serial_number, rsp->serial_number, 16);  // 序列号

    // 将字节数组转换为字符串
    auto manufacturer = std::string(reinterpret_cast<char*>(optical_module_info.manufacturer), 
                                    sizeof(optical_module_info.manufacturer));
    auto part_number = std::string(reinterpret_cast<char*>(optical_module_info.part_number), 
                                   sizeof(optical_module_info.part_number));
    auto serial_number = std::string(reinterpret_cast<char*>(optical_module_info.serial_number), 
                                     sizeof(optical_module_info.serial_number));
    
    // 转换工作电压（网络字节序 -> 主机字节序，微伏 -> 毫伏）
    auto supply_voltage = covert_micro_to_milli(mc::ntoh(rsp->working_voltage));

    // 去除尾部的空格
    manufacturer.erase(manufacturer.find_last_not_of(' ') + 1);
    part_number.erase(part_number.find_last_not_of(' ') + 1);
    serial_number.erase(serial_number.find_last_not_of(' ') + 1);

    // 验证解析结果
    EXPECT_STREQ(manufacturer.c_str(), "LUXSHARE-ICT");     // 立讯精密
    EXPECT_STREQ(part_number.c_str(), "L99QF020-SD-R");     // 型号
    EXPECT_STREQ(serial_number.c_str(), "Z00A2R1709000061");  // 序列号
    EXPECT_EQ(supply_voltage, 3.25);  // 工作电压3.25V
}

} // namespace test
} // namespace hisi
} // namespace pcie_nic_card
} // namespace drivers

